package com.dongnao.dnhttp.ywynet;

import android.support.annotation.NonNull;
import android.util.Log;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.concurrent.Executor;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Created by ywy on 2018-04-28.
 */
public class ConnectionPool {

    private static ThreadFactory threadFactory = new ThreadFactory() {
        @Override
        public Thread newThread(@NonNull Runnable r) {
            Thread result = new Thread(r, "HttpClient ConnectionPool");
            result.setDaemon(true);
            return result;
        }
    };

    private static final Executor executor = new ThreadPoolExecutor(0,
            Integer.MAX_VALUE, 60l, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory);


    /**
     * 每个连接的最大存活时间
     */
    private final long keepAliveDuration;

    private final Runnable cleanRunnable = new Runnable() {
        @Override
        public void run() {
            while(true){
                long waitTimes = cleanup(System.currentTimeMillis());
                if(waitTimes == -1){
                    return;
                }
                if(waitTimes > 0 ){
                    synchronized (ConnectionPool.this){
                        try {
                            ConnectionPool.this.wait(waitTimes);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    };

    private final Deque<HttpConnection> connections = new ArrayDeque<>();

    private boolean cleanupRunning;

    public ConnectionPool(){
        this(1,TimeUnit.MINUTES);
    }

    public ConnectionPool(long keepAliveDuration , TimeUnit timeUnit){
        this.keepAliveDuration = timeUnit.toMillis(keepAliveDuration);
    }



    public HttpConnection get(String host , int port){
        Iterator<HttpConnection> iterator = connections.iterator();
        while(iterator.hasNext()){
            HttpConnection connection = iterator.next();
            if(connection.isSameAddress(host , port)){
                iterator.remove();
                return connection;
            }
        }
        return null;
    }

    public void put(HttpConnection connection){
        if(!cleanupRunning){
            cleanupRunning = true;
            executor.execute(cleanRunnable);
        }
        connections.add(connection);
    }

    long cleanup(long now){
        long longestIdleDuration = -1;
        synchronized (this){
            for (Iterator<HttpConnection> iterator = connections.iterator(); iterator.hasNext();) {
                HttpConnection connection = iterator.next();
                long idleDuration = now - connection.lastUsetime;
                if(idleDuration > keepAliveDuration){
                    connection.closeQuietly();
                    iterator.remove();
                    Log.e("Pool", "移出连接池");
                    continue;

                }
                //获得最大闲置时间
                if (longestIdleDuration < idleDuration) {
                    longestIdleDuration = idleDuration;
                }
            }

            if(longestIdleDuration >= 0){
                return keepAliveDuration - longestIdleDuration;
            }else{
                cleanupRunning = false;
                return longestIdleDuration;
            }
        }

    }

}
